package stat;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import seg.RelativeRho;
import doc.SampledPoint;
import doc.Stroke;

public class Threshold {

	public static class DataEntity {
		public double mean;
		public double var;

		public DataEntity(double m, double v) {
			mean = m;
			var = v;
		}

		public String toString() {
			return "data entity = (" + mean + "," + var + ")";
		}
	}

	private static int K = 3;

	public static final String TRAIN_SAMPLE_DIR = "C:\\Workspace\\Exp\\segmentation\\train\\";

	private static List<DataEntity> constData;

	private static List<DataEntity> varData;

	private static void initDataSet() {
		constData = new ArrayList<DataEntity>();
		varData = new ArrayList<DataEntity>();

		String pre = TRAIN_SAMPLE_DIR + "train.";

		String suf = "const.";
		for (int i = 1; i <= 30; i++) {
			String file = pre + suf + Integer.toString(i);
			Stroke s = parseStrokeFromFile(new File(file));
			constData.add(processStroke(s));
		}

		suf = "var.";
		for (int i = 1; i <= 20; i++) {
			String file = pre + suf + Integer.toString(i);
			Stroke s = parseStrokeFromFile(new File(file));
			varData.add(processStroke(s));
		}
	}

	private static double calcMaxOfConst() {
		double maxOfConst = 0;
		for (DataEntity en : constData) {
//			System.out.println("const: " + en.toString());
			if (en.var > maxOfConst)
				maxOfConst = en.var;
		}
		return maxOfConst;
	}

	private static double calcMinOfVar() {
		double minOfVar = Double.MAX_VALUE;
//		System.out.println("var data");
		for (DataEntity en : varData) {
//			System.out.println("var: " + en.toString());
			if (minOfVar > en.var)
				minOfVar = en.var;
		}
		return minOfVar;
	}

	public static void printDataSet() {
		System.out.println("K = " + getK());
		System.out.println("  max const: " + calcMaxOfConst());
		System.out.println("  min var: " + calcMinOfVar());
	}

	public static DataEntity processStroke(Stroke s) {
		s.preprocess();

		SampledPoint ps[] = s.getPoints();
		double rhos[] = RelativeRho.calcRhos(ps, getK());

		DataEntity en = new DataEntity(GaussianModel.calcMean(rhos), GaussianModel.calcDev(rhos));
		return en;
	}

	public static Stroke parseStrokeFromFile(File file) {
		return Stroke.getFromFile(file);
	}

	public static int getK() {
		return K;
	}

	public static void setK(int k) {
		K = k;
	}

	public static void train() {
		threshold = new HashMap<Integer, Double>();

		System.out.println("training ... ");
		for (int i = 2; i < 20; i++) {
			Threshold.setK(i);
			Threshold.initDataSet();

			double max = calcMaxOfConst();
			double min = calcMinOfVar();
//			if (max > min)
//				System.err.println("train fail for k = " + i);
			String s = "K = " + i + " | max = " + max + ", " + "min = " + min;
			if (max <= min) {
				System.out.println(s);
				System.out.println("\tthreshold = " + (max + min) / 2);
			} else {
				System.err.println(s);
			}
			threshold.put(i, min);
		}


	}


	private static HashMap<Integer, Double> threshold;

	public static double thresholdOf(int k) {
		if (threshold == null) {
			train();
//			System.out.println(threshold.values());
		}
		System.out.println("[[[[[[ " + threshold.get(k));
		return threshold.get(k);
	}
}
